#ifdef WIN32
#include "WinInit.h"
#include <winsock.h>

DEF_BEG_LIBTOOLS

long CWinInit::_initCount = 0;

CWinInit::CWinInit()
{
	if (::InterlockedIncrement(&_initCount) == 1)
	{
		WORD dwVersion = MAKEWORD(2, 2);
		WSADATA cvData;
		WSAStartup(dwVersion, &cvData);
	}
}

CWinInit::~CWinInit()
{
	if (::InterlockedDecrement(&_initCount) == 0)
	{
		::WSACleanup();
	}
}

inline LPFN_ACCEPTEX GetAcceptExLpfn(SOCKET s)
{
	LPFN_ACCEPTEX lpfnAcceptEx;
	DWORD bytes;
	GUID guidAcceptEx = WSAID_ACCEPTEX;
	int nRet = WSAIoctl(s,
		SIO_GET_EXTENSION_FUNCTION_POINTER,
		&guidAcceptEx,
		sizeof(guidAcceptEx),
		&lpfnAcceptEx,
		sizeof(lpfnAcceptEx),
		&bytes,
		NullPtr,
		NullPtr
	);
	if (nRet == SOCKET_ERROR) {
		return NullPtr;
	}

	return lpfnAcceptEx;
}

inline LPFN_GETACCEPTEXSOCKADDRS GetGetAcceptExSockaddrsLpfn(SOCKET s)
{
	GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
	LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs;
	DWORD bytes;
	WSAIoctl(s,
		SIO_GET_EXTENSION_FUNCTION_POINTER,
		&guidGetAcceptExSockaddrs,
		sizeof(guidGetAcceptExSockaddrs),
		&lpfnGetAcceptExSockaddrs,
		sizeof(lpfnGetAcceptExSockaddrs),
		&bytes,
		NullPtr,
		NullPtr
	);
	return lpfnGetAcceptExSockaddrs;
}

inline LPFN_CONNECTEX GetConnectExLpfn(SOCKET s)
{
	GUID guidGetConnectEx = WSAID_CONNECTEX;
	LPFN_CONNECTEX lpfnConnectEx;
	DWORD bytes;
	WSAIoctl(s,
		SIO_GET_EXTENSION_FUNCTION_POINTER,
		&guidGetConnectEx,
		sizeof(guidGetConnectEx),
		&lpfnConnectEx,
		sizeof(lpfnConnectEx),
		&bytes,
		NullPtr,
		NullPtr);

	return lpfnConnectEx;
}

DEF_END_LIBTOOLS

#endif // WIN32